package tv.dyndns.kishibe.client.setting;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;

import tv.dyndns.kishibe.client.Service;

import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.uibinder.client.UiHandler;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.Widget;

public class PanelSettingLimitedUser extends Composite {
	private static final Logger logger = Logger.getLogger(PanelSettingLimitedUser.class.getName());
	private static PanelSettingLimitedUserUiBinder uiBinder = GWT
			.create(PanelSettingLimitedUserUiBinder.class);

	interface PanelSettingLimitedUserUiBinder extends UiBinder<Widget, PanelSettingLimitedUser> {
	}

	@UiField
	FlowPanel panelUserCodes;
	@UiField
	TextBox textBoxUserCode;
	@UiField
	Button buttonUserCodeAdd;
	@UiField
	Button buttonUserCodeClear;
	@UiField
	FlowPanel panelRemoteAddresses;
	@UiField
	TextBox textBoxRemoteAddress;
	@UiField
	Button buttonRemoteAddressAdd;
	@UiField
	Button buttonRemoteAddressClear;

	public PanelSettingLimitedUser() {
		initWidget(uiBinder.createAndBindUi(this));
		updateUserCodes();
		updateRemoteAddresses();
	}

	private void updateUserCodes() {
		Service.Util.getInstance().getLimitedUserCodes(callbackGetLimitedUserCodes);
	}

	private void updateRemoteAddresses() {
		Service.Util.getInstance().getLimitedRemoteAddresses(callbackGetLimitedRemoteAddresses);
	}

	private final AsyncCallback<Set<Integer>> callbackGetLimitedUserCodes = new AsyncCallback<Set<Integer>>() {
		@Override
		public void onSuccess(Set<Integer> result) {
			final List<Integer> userCodes = new ArrayList<Integer>(result);
			Collections.sort(userCodes);
			panelUserCodes.clear();
			for (final int userCode : userCodes) {
				final Button button = new Button("" + userCode);
				button.addClickHandler(new ClickHandler() {
					@Override
					public void onClick(ClickEvent event) {
						Service.Util.getInstance().removeLimitedUserCode(userCode,
								callbackUpdateUserCodes);
					}
				});
				panelUserCodes.add(button);
			}
		}

		@Override
		public void onFailure(Throwable caught) {
			logger.log(Level.WARNING, "制限されたユーザーコードの取得に失敗しました", caught);
		}
	};
	private final AsyncCallback<Void> callbackUpdateUserCodes = new AsyncCallback<Void>() {
		@Override
		public void onSuccess(Void result) {
			updateUserCodes();
		}

		@Override
		public void onFailure(Throwable caught) {
			logger.log(Level.WARNING, "ユーザーコードの変更に失敗しました", caught);
		}
	};

	private final AsyncCallback<Set<String>> callbackGetLimitedRemoteAddresses = new AsyncCallback<Set<String>>() {
		@Override
		public void onSuccess(Set<String> result) {
			final List<String> remoteAddresses = new ArrayList<String>(result);
			Collections.sort(remoteAddresses);
			panelRemoteAddresses.clear();
			for (final String remoteAddress : remoteAddresses) {
				final Button button = new Button(remoteAddress);
				button.addClickHandler(new ClickHandler() {
					@Override
					public void onClick(ClickEvent event) {
						if (!Window.confirm("リモートアドレス " + remoteAddress + " を削除しますか？")) {
							return;
						}

						Service.Util.getInstance().removeLimitedRemoteAddress(remoteAddress,
								callbackUpdateRemoteAddress);
					}
				});
				panelRemoteAddresses.add(button);
			}
		}

		@Override
		public void onFailure(Throwable caught) {
			logger.log(Level.WARNING, "リモートアドレスの取得に失敗しました", caught);
		}
	};
	private final AsyncCallback<Void> callbackUpdateRemoteAddress = new AsyncCallback<Void>() {
		@Override
		public void onSuccess(Void result) {
			updateRemoteAddresses();
		}

		@Override
		public void onFailure(Throwable caught) {
			logger.log(Level.WARNING, "リモートアドレスの更新に失敗しました", caught);
		}
	};

	@UiHandler("buttonUserCodeAdd")
	void onButtonUserCodeAdd(ClickEvent e) {
		final int userCode = Integer.parseInt(textBoxUserCode.getText());
		Service.Util.getInstance().addLimitedUserCode(userCode, callbackUpdateUserCodes);
	}

	@UiHandler("buttonUserCodeClear")
	void onButtonUserCodeClear(ClickEvent e) {
		Service.Util.getInstance().clearLimitedUserCode(callbackUpdateUserCodes);
	}

	@UiHandler("buttonRemoteAddressAdd")
	void onButtonRemoteAddressAdd(ClickEvent e) {
		final String remoteAddress = textBoxRemoteAddress.getText();
		Service.Util.getInstance().addLimitedRemoteAddress(remoteAddress,
				callbackUpdateRemoteAddress);
	}

	@UiHandler("buttonRemoteAddressClear")
	void onButtonRemoteAddressClear(ClickEvent e) {
		Service.Util.getInstance().clearLimitedRemoteAddress(callbackUpdateRemoteAddress);
	}
}
